package top.tresman.cxxcommon.exception;


import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ResponseBody;
import top.tresman.cxxcommon.entity.Result;
import top.tresman.cxxcommon.entity.constants.ErrorCodeEnum;

import java.util.List;
import java.util.Objects;

/**
 * @author cxx
 * @desc 统一异常处理
 */
@Slf4j
@ControllerAdvice
public class ExceptionHandler {

    /**
     * 捕获@Valid抛出的异常 即 参数错误
     *
     * @param e 错误类型
     * @return 返回值
     */
    @org.springframework.web.bind.annotation.ExceptionHandler({BindException.class})
    @ResponseBody
    public Result<Void> handleBindException(BindException e) {
        log.error("[ @Valid异常捕获 ] {}", e.getMessage(), e);
        if (Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage() != null && e.getBindingResult().getFieldError().getDefaultMessage().length() > 100) {
            return Result.error(ErrorCodeEnum.BAD_ARGS, "参数错误");
        } else {
            return Result.error(ErrorCodeEnum.BAD_ARGS, e.getBindingResult().getFieldError().getDefaultMessage());
        }
    }

    /**
     * 捕获@Valid抛出的异常 即 参数错误
     *
     * @param e 错误类型
     * @return 返回值
     */
    @org.springframework.web.bind.annotation.ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public Result<Void> handleValidationBodyException(MethodArgumentNotValidException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();

        FieldError error = fieldErrors.getFirst();
        for (FieldError err : fieldErrors) {
            log.warn("异常实体：{},异常字段: {},异常值: {},异常信息: {}", err.getObjectName(), err.getField(),
                    err.getRejectedValue(), err.getDefaultMessage());
        }

        return Result.error(ErrorCodeEnum.BAD_ARGS, error.getDefaultMessage());
    }

    /**
     * @param e 错误类型
     * @return 返回值
     */
    @org.springframework.web.bind.annotation.ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseBody
    public Result<Void> handleValidationBodyException(HttpMessageNotReadableException e) {
        log.error("[ HttpMessageNotReadableException ] {}", e.getMessage(), e);
        return Result.error(ErrorCodeEnum.BAD_ARGS, e.getMessage());
    }

    @org.springframework.web.bind.annotation.ExceptionHandler(ApiException.class)
    @ResponseBody
    public Result<Void> handleValidationBodyException(ApiException e) {
        log.error("[ @Valid异常捕获 ] {}", e.getMessage(), e);
        return Result.error(e.getCode(), e.getMessage());
    }

    @org.springframework.web.bind.annotation.ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Result<Void> handler(Exception e) {
        log.error(e.getMessage(), e);

        return Result.error(ErrorCodeEnum.SYS_ERR, "服务器开小差了~ 请稍后重试~ ");
    }
}
